#pragma once
#include "../common/dispatcher.hpp"
#include "../client/rpc_client.hpp"
#include "../client/requestor.hpp"
#include "rpc_router.hpp"
#include "rpc_registry.hpp"
#include "../client/rpc_caller.hpp"
#include "rpc_topic.hpp"

namespace RPC
{
    namespace server
    {
        class RegistryServer
        {
        public: 
            using ptr = std::shared_ptr<RegistryServer>;
            RegistryServer(int port)
                :_pd_manager(std::make_shared<PDManager>())
                ,_dispatcher(std::make_shared<RPC::Dispatcher>())
            {
                auto service_cb = std::bind(&PDManager::onServiceRequest, _pd_manager.get(),
                        std::placeholders::_1, std::placeholders::_2);
                
                _dispatcher->registerHandler<ServiceRequest>(MType::REQ_SERVICE, service_cb);


                _server = RPC::ServerFactory::create(port);
                auto message_cb = std::bind(&RPC::Dispatcher::onMessage, _dispatcher.get(),
                        std::placeholders::_1, std::placeholders::_2);
                _server->setMessageCallback(message_cb);
                auto close_cb = std::bind(&RegistryServer::onConnShutdown, this, std::placeholders::_1);
                _server->setCloseCallback(close_cb);
                _server->start();
            }

            void start()
            {
                _server->start();
            }

        private:
            void onConnShutdown(const BaseConnection::ptr &conn)
            {
                _pd_manager->onConnShutdown(conn);
            }
        private:
            PDManager::ptr _pd_manager;
            Dispatcher::ptr _dispatcher;
            BaseServer::ptr _server;
        };

        class RpcServer
        {
        public:
            using ptr = std::shared_ptr<RpcServer>;
            //两套地址信息, rpc服务提供端地址信息, 必须是服务器对外访问地址.
            //注册中心服务端地址信息, 启用服务注册后的连接中心进行服务注册使用的.
            RpcServer(const Address& access_addr,
                    bool enableRegistry = false, 
                    const Address& registry_server_addr = Address())
                :_enableRegistry(enableRegistry)
                ,_access_addr(access_addr)
                ,_router(std::make_shared<RPC::server::RpcRouter>())
                ,_dispatcher(std::make_shared<RPC::Dispatcher>())
            {
                if(enableRegistry)
                {
                    _reg_client = std::make_shared<client::RegistryClient>(
                        registry_server_addr.first, registry_server_addr.second);
                }

                //当前成员server是提供rpc服务的;
                auto rpc_cb = std::bind(&RPC::server::RpcRouter::onRpcRequest, _router.get(),
                        std::placeholders::_1, std::placeholders::_2);

                _dispatcher->registerHandler<RPC::RpcRequest>(RPC::MType::REQ_RPC, rpc_cb);
                _server = RPC::ServerFactory::create(_access_addr.second);

                auto message_cb = std::bind(&RPC::Dispatcher::onMessage, _dispatcher.get(), 
                std::placeholders::_1, std::placeholders::_2);
                _server->setMessageCallback(message_cb);
            }
            void RegistryMethod(const ServiceDiscribe::ptr& service)
            {
                if(_enableRegistry)
                {
                    _reg_client->registryMethod(service->method(), _access_addr);
                }
                _router->registerMethod(service);
            }
            void start()
            {
                _server->start();
            }
        private:
            bool _enableRegistry;
            Address _access_addr;
            client::RegistryClient::ptr _reg_client;
            RpcRouter::ptr _router;
            Dispatcher::ptr _dispatcher;
            BaseServer::ptr _server;
        };

        class TopicServer
        {
        public: 
            using ptr = std::shared_ptr<RegistryServer>;
            TopicServer(int port)
                :_topic_manager(std::make_shared<TopicManager>())
                ,_dispatcher(std::make_shared<RPC::Dispatcher>())
            {
                auto topic_cb = std::bind(&RPC::server::TopicManager::onTpoicRequest, _topic_manager.get(),
                        std::placeholders::_1, std::placeholders::_2);
                
                _dispatcher->registerHandler<TopicRequest>(MType::REQ_SERVICE, topic_cb);
                

                _server = RPC::ServerFactory::create(port);
                auto message_cb = std::bind(&RPC::Dispatcher::onMessage, _dispatcher.get(),
                        std::placeholders::_1, std::placeholders::_2);
                _server->setMessageCallback(message_cb);
                auto close_cb = std::bind(&TopicServer::onConnShutdown, this, std::placeholders::_1);
                _server->setCloseCallback(close_cb);
                _server->start();
            }

            void start()
            {
                _server->start();
            }

        private:
            void onConnShutdown(const BaseConnection::ptr &conn)
            {
                _topic_manager->onShutdown(conn);
            }
        private:
            TopicManager::ptr _topic_manager;
            Dispatcher::ptr _dispatcher;
            BaseServer::ptr _server;
        };
    }
}